package com.yjz.common.thread;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.IntRange;

import com.yjz.log.JLog;

import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 作用 : 自定义线程池(支持设置线程的优先级，以及支持线程的暂停和恢复)
 * 作者 : yjz
 * 时间 : 2025/2/8 13:57
 */
public class YThreadPool {

    public static volatile YThreadPool sInstance;
    private ThreadPoolExecutor threadPoolExecutor;
    private static Handler mainHandler = new Handler(Looper.getMainLooper());
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition;
    private boolean isPaused;

    private YThreadPool() {
        init();
    }

    public static YThreadPool getInstance() {
        if (sInstance == null) {
            synchronized (YThreadPool.class) {
                if (sInstance == null) {
                    sInstance = new YThreadPool();
                }
            }
        }
        return sInstance;
    }

    private void init() {
        this.condition = lock.newCondition();
        // 核心线程数
        int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
        // 最大线程数
        int maxPoolSize = corePoolSize * 2 + 1;
        // 存活时间
        int keepAlive = 3000;
        // 存活单位
        TimeUnit timeUnit = TimeUnit.SECONDS;
        // 优先级任务队列
        PriorityBlockingQueue<Runnable> blockingQueue = new PriorityBlockingQueue<>();
        // 原子类型Long，记录线程序号
        AtomicLong atomicLong = new AtomicLong(0);

        threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAlive, timeUnit, blockingQueue, runnable -> {
            Thread thread = new Thread(runnable);
            thread.setName("Y-ThreadPool" + atomicLong.getAndIncrement());
            return thread;
        }) {
            //  线程执行任务之前，回调的方法
            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                // 判断线程是否处于暂停状态
                if (isPaused) {
                    lock.lock();
                    try {
                        // 线程处于暂停状态，将线程挂起
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        // 释放锁
                        lock.unlock();
                    }
                }
            }

            // 执行完任务之后，回调的方法
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                // 可以监控线程池耗时任务,线程创建数量,正在运行的数量
                JLog.e("thread", "已执行完的任务的优先级是：" + ((PriorityRunnable) r).priority);
            }
        };
    }

    /**
     * 默认执行最低优先级的任务
     */
    public void execute(Runnable runnable) {
        execute(0, runnable);
    }

    /**
     * 执行指定优先级的任务
     *
     * @param priority 优先级
     * @param runnable 任务
     */
    public void execute(@IntRange(from = 0, to = 10) int priority, Runnable runnable) {
        threadPoolExecutor.execute(new PriorityRunnable(priority, runnable));
    }

    public void execute(@IntRange(from = 0, to = 10) int priority, Callable<?> callable) {
        threadPoolExecutor.execute(new PriorityRunnable(priority, callable));
    }

    /**
     * 暂停线程
     */
    public void pause() {
        lock.lock();
        try {
            if (isPaused) return;
            isPaused = true;
        } finally {
            lock.unlock();
        }
        JLog.e("TAG", "hiExecutor is paused");
    }

    /**
     * 恢复线程
     */
    public void resume() {
        lock.lock();
        try {
            if (!isPaused) return;
            isPaused = false;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
        JLog.eTag("TAG", "hiExecutor is resumed");
    }

    /**
     * 带返回结果的任务执行
     */
    public abstract static class Callable<T> implements Runnable {
        public void onPrepare() {
            //TODO 转菊花
        }

        public abstract T onBackground();

        public abstract void onCompleted(T t);

        @Override
        public void run() {
            mainHandler.post(() -> {
                onPrepare();
            });
            T t = onBackground();
            // 移除所有消息.防止需要执行onCompleted了，onPrepare还没被执行，那就不需要执行了
            mainHandler.removeCallbacksAndMessages(null);
            mainHandler.post(() -> {
                onCompleted(t);
            });
        }
    }

    /**
     * 带优先级的任务队列
     */
    static class PriorityRunnable implements Comparable<PriorityRunnable>, Runnable {

        public int priority;
        private final Runnable runnable;

        public PriorityRunnable(int priority, Runnable runnable) {
            this.priority = priority;
            this.runnable = runnable;
        }

        @Override
        public void run() {
            this.runnable.run();
        }

        @Override
        public int compareTo(PriorityRunnable other) {
            //实现Comparable接口,复写该方法,用以比较各任务的优先级排序
            if (this.priority < other.priority) {
                return 1;
            } else if (this.priority > other.priority) {
                return -1;
            } else {
                return 0;
            }
        }
    }

}
